﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using ABC.Core.Configuration;
using ABC.Core.Providers;
using Castle.Core.Logging;
using RosService;
using RosService.Data;
using Хранилище = RosService.Data.Хранилище;

namespace ABC.Business.Models
{
    public class RosModel
    {
        private readonly IApplicationSettingsProvider ApplicationSettingsProvider;
    	private readonly ILogger logger;

        public RosModel()
        {
        	this.logger = IoC.Resolve<ILogger>();
            ApplicationSettingsProvider = IoC.Resolve<IApplicationSettingsProvider>();
        }

        public DataRow GetEntityById(string type, string id, string[] outputFields)
        {
            using (var client = new Client())
            {
                var query = new Query();
                query.ДобавитьТипы(type);
                query.ДобавитьУсловиеПоиска("id_node", id);
                query.ДобавитьВыводимыеКолонки(outputFields);
                return client.Архив.Поиск(query).AsEnumerable().FirstOrDefault();
            }
        }

        public DataRow GetEntityByIdFromCache(string id, string cacheName, string[] outputFields)
        {
            using (var client = new Client())
            {
                var query = new Query { CacheName = cacheName };

                query.ДобавитьУсловиеПоиска("id_node", id);
                query.ДобавитьВыводимыеКолонки(outputFields);

                return client.Архив.Поиск(query).AsEnumerable().FirstOrDefault();
            }
        }

        public DataRow GetEntityById(string type, string id, Dictionary<string, object> filters, string[] outputFields)
        {
            using (var client = new Client())
            {
                var query = new Query();
                query.ДобавитьТипы(type);
                query.ДобавитьУсловиеПоиска("id_node", Convert.ToDecimal(id));
                foreach (var filter in filters)
                {
                    query.ДобавитьУсловиеПоиска(filter.Key, filter.Value, Query.Оператор.Соодержит);
                }
                query.ДобавитьВыводимыеКолонки(outputFields);
                query.ДобавитьГруппировки();
                return client.Архив.Поиск(query).AsEnumerable().FirstOrDefault();
            }
        }

        public List<DataRow> GetEntities(string type, string filterField, string filterQuery, string[] outputFields)
        {
            using (var client = new Client())
            {
                var query = new Query();

                query.ДобавитьТипы(type);
                query.ДобавитьУсловиеПоиска(filterField, filterQuery, Query.Оператор.Соодержит);

                if (outputFields != null)
                    query.ДобавитьВыводимыеКолонки(outputFields);

                return client.Архив.Поиск(query).AsEnumerable().ToList();
            }
        }

        public List<DataRow> GetEntities(string queryStr, Dictionary<string, object> filters)
        {
            using (var client = new Client())
            {
                var query = new Query(queryStr);
                if (filters != null)
                {
                    foreach (var filter in filters)
                    {
                        query.ДобавитьУсловиеПоиска(filter.Key, filter.Value, Query.Оператор.Соодержит);
                    }
                }
                return client.Архив.Поиск(query).AsEnumerable().ToList();
            }
        }

        public TableValue GetTableEntities(string queryStr, int numberOfOutputData = 0, int page = -1)
        {
            using (var client = new Client())
            {
                var query = new Query(queryStr);
                if (page != -1)
                {
                    query.Страница = page;
                }
                if (numberOfOutputData != 0)
                {
                    query.КоличествоВыводимыхДанных = numberOfOutputData;
                }
                return client.Архив.Поиск(query);
            }
        }

        public List<DataRow> GetEntities(string type, string id)
        {
            using (var client = new Client())
            {
                var query = new Query();
                query.ДобавитьМестоПоиска(Convert.ToDecimal(id), 1);
                query.ДобавитьТипы(type);

                return client.Архив.Поиск(query).AsEnumerable().ToList();
            }
        }
        public TableValue GetEntities(string type, string id, Dictionary<string, Query.НаправлениеСортировки> orders, Dictionary<string, object> filters, string[] outputFields, int numberOfOutputData = 0, int page = -1)
        {

            using (var client = new Client())
            {
                var query = new Query();

                query.ДобавитьТипы(type);
                foreach (var order in orders.Where(x => x.Key != string.Empty))
                {
                    query.ДобавитьСортировку(order.Key, order.Value);
                }
                query.ДобавитьМестоПоиска(id, 1);

                if (page != -1)
                {
                    query.Страница = page;
                }
                if (numberOfOutputData != 0)
                {
                    query.КоличествоВыводимыхДанных = numberOfOutputData;
                }
                if (filters != null)
                {
                    foreach (var filter in filters)
                    {
                        query.ДобавитьУсловиеПоиска(filter.Key, filter.Value, Query.Оператор.Равно);
                    }
                }
                if (outputFields != null)
                    query.ДобавитьВыводимыеКолонки(outputFields);
                return client.Архив.Поиск(query);
            }
        }

        public TableValue GetEntitiesFromCache(string cacheName, Dictionary<string, object> filters, string[] outputFields, out int pageCount, int numberOfOutputData = 0, int page = -1)
        {
            using (var client = new Client())
            {
                var query = new Query();
                query.CacheName = cacheName;
                if (outputFields != null)
                    query.ДобавитьВыводимыеКолонки(outputFields);
                foreach (var filter in filters)
                {
                    query.ДобавитьУсловиеПоиска(filter.Key, filter.Value, Query.Оператор.Равно);
                }
                if (page != -1)
                {
                    query.Страница = page;
                }
                if (numberOfOutputData != 0)
                {
                    query.КоличествоВыводимыхДанных = numberOfOutputData;
                }
                var result = client.Архив.Поиск(query);
                pageCount = result.PageCount;
                return result;
            }
        }

        public void UpdateEntityValue(string id, string field, object value)
        {
            using (var client = new Client())
            {
                client.Архив.СохранитьЗначение(Convert.ToDecimal(id), field, value);
            }
        }

        public void UpdateEntityValueCallCenter(string id, string field, object value)
        {
            try
            {
                using (var client = new HyperСloud.Client(ApplicationSettingsProvider.UserNameCallCenter))
                {
                    client.Set(Convert.ToDecimal(id), field, value);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message, ex);
            }
        }

        public void DeleteEntity(string id, bool removeDependencies)
        {
            using (var client = new Client())
            {
                client.Архив.УдалитьРаздел(removeDependencies, Convert.ToDecimal(id), Хранилище.Оперативное);
            }
        }

        public T GetEntityValue<T>(string id, string field)
        {
            using (var client = new Client())
            {
                return client.Архив.ПолучитьЗначение<T>(id, field);
            }
        }

        public decimal AddEntity(string ownerId, string type, Dictionary<string, object> values)
        {
            using (var client = new Client())
            {
                decimal owner;

                if (decimal.TryParse(ownerId, out owner))
                {
                    return client.Архив.ДобавитьРаздел(owner, type, values);
                }

                return client.Архив.ДобавитьРаздел(ownerId, type, values);
            }
        }

        public T GetConstantValue<T>(string name)
        {
            using (var client = new Client())
            {
                return client.Архив.ПолучитьКонстанту<T>(name);
            }
        }

        public void DeleteEntity(string id)
        {
            using (var client = new HyperСloud.Client())
            {
                client.Delete(Convert.ToDecimal(id));
            }
        }
        public List<DataRow> GetEntitiesActions(string type, string id, string orderField, Query.НаправлениеСортировки order, Dictionary<string, object> filters, string[] outputFields)
        {
            using (var client = new Client())
            {
                var query = new Query();

                query.ДобавитьТипы(type);
                query.ДобавитьСортировку(orderField, order);
                query.ДобавитьМестоПоиска(id, 1);
                query.ДобавитьУсловиеПоиска("НачалоДействия", DateTime.Now, Query.Оператор.МеньшеРавно);
                query.ДобавитьУсловиеПоиска("ОкончаниеДействия", DateTime.Now, Query.Оператор.БольшеРавно);
                foreach (var filter in filters)
                {
                    query.ДобавитьУсловиеПоиска(filter.Key, filter.Value, Query.Оператор.Соодержит);
                }
                if (outputFields != null)
                    query.ДобавитьВыводимыеКолонки(outputFields);

                return client.Архив.Поиск(query).AsEnumerable().ToList();
            }
        }

        public decimal SaveFile(string ownerId, HttpPostedFileBase data)
        {
            using (var client = new Client())
            {
                var buffer = new byte[data.InputStream.Length];
                data.InputStream.Position = 0;
                data.InputStream.Read(buffer, 0, buffer.Length);
                return client.Файлы.СохранитьФайлПолностью(Convert.ToDecimal(ownerId), null, data.FileName, null, buffer, RosService.Files.Хранилище.Оперативное, client.Пользователь, client.Домен);
            }
        }

        public decimal SaveFileToCallCenter(string ownerId, string fileName, byte[] data)
        {
            try
            {
                using (var client = new HyperСloud.Files(ApplicationSettingsProvider.UserNameCallCenter))
                {
                    return client.Set(ownerId, fileName, data);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message, ex);
            }
            return 0M;
        }

        public byte[] GetFile(string id)
        {
            using (var client = new HyperСloud.Files())
            {
                return client.Get(id);
            }
        }

        public IEnumerable<ФайлИнформация> GetFilesInfo(string id)
        {
            using (var client = new HyperСloud.Files())
            {
                return client.GetFiles(id);
            }
        }

        public decimal AddEntityToCallCenter(string ownerId, string type, Dictionary<string, object> values)
        {
            try
            {
                using (var client = new HyperСloud.Client(ApplicationSettingsProvider.UserNameCallCenter))
                {
                    return client.AddAsync(ownerId, type, values);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message, ex);
            }
            return 0M;
        }

        public T GetEntityValueCallCenter<T>(string id, string field)
        {
            try
            {
                using (var client = new HyperСloud.Client(ApplicationSettingsProvider.UserNameCallCenter))
                {
                    return client.Get<T>(id, field);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message, ex);
            }
            return default(T);
        }

        public TableValue GetEntitiesFromCallCenter(string type, string id, Dictionary<string, Query.НаправлениеСортировки> orders, Dictionary<string, object> filters, string[] outputFields, int numberOfOutputData = 0, int page = -1, string cacheName = "")
        {
            try
            {
                using (var client = new HyperСloud.Client(ApplicationSettingsProvider.UserNameCallCenter))
                {
                    var query = new Query();

                    query.ДобавитьТипы(type);
                    foreach (var order in orders.Where(x => x.Key != string.Empty))
                    {
                        query.ДобавитьСортировку(order.Key, order.Value);
                    }

                    if (!string.IsNullOrEmpty(cacheName))
                    {
                        query.CacheName = cacheName;
                    }
                    else
                    {
                        query.ДобавитьМестоПоиска(id, 1);
                    }
                    if (page != -1)
                    {
                        query.Страница = page;
                    }
                    if (numberOfOutputData != 0)
                    {
                        query.КоличествоВыводимыхДанных = numberOfOutputData;
                    }
                    if (filters != null)
                    {
                        foreach (var filter in filters)
                        {
                            query.ДобавитьУсловиеПоиска(filter.Key, filter.Value, Query.Оператор.Равно);
                        }
                    }
                    if (outputFields != null)
                        query.ДобавитьВыводимыеКолонки(outputFields);
                    return client.Search(query);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message, ex);
            }
            return new TableValue();
        }
    }
}
